#include "instrumentview.h"
#include <boost/bind.hpp>
#include "app.h"
#include "song.h"
#include "instrument.h"
#include "patterneditor.h"
using namespace boost;
using namespace std;

InstrumentView::InstrumentView(Rect r, App *pApp) 
: View(r, pApp->skin()->font()), m_pApp(pApp), 
  m_instList(Rect(), m_pApp), 
  m_instAddButton(pApp->skin()->buttonSkin(Skin::AddButton)),
  m_instDelButton(pApp->skin()->buttonSkin(Skin::DelButton)) {
     setRect(m_rect);
     m_views.push_back(&m_instList);
     m_views.push_back(&m_instAddButton);
     m_views.push_back(&m_instDelButton);
     loadInstList();
     connect();
}

void InstrumentView::connect() {
     PatternEditor *pEditor = m_pApp->patternEditor();
     m_instListConn = m_instList.onChange(bind(&InstrumentView::updateEdInstNum, this, _1));
     m_edInstConn = pEditor->onInstChange(bind(&InstrumentView::updateListInstNum, this, _1));
     pEditor->song()->onLoad(bind(&InstrumentView::loadInstList, this));
     m_instList.onNameChange(bind(&PatternEditor::setCurInstName, pEditor, _1));
     m_instAddButton.onClick(bind(&InstrumentView::addInst, this));
     m_instDelButton.onClick(bind(&InstrumentView::delInst, this));
}

void InstrumentView::updateEdInstNum(int inst) {
     signals2::shared_connection_block block(m_edInstConn);
     m_pApp->patternEditor()->setCurInstNum(inst);
}

void InstrumentView::updateListInstNum(int inst) {
     signals2::shared_connection_block block(m_instListConn);
     m_instList.setCurIndex(inst);
}

void InstrumentView::setRect(Rect r) {
     m_rect = r;
     const int pad = InstrumentView::Padding;
     Rect lr = Rect(m_rect.x() + pad, m_rect.y() + pad, 
		    150, m_rect.height() - pad * 2);
     m_instList.setRect(lr);
     Rect br = m_instAddButton.rect();
     m_instAddButton.setRect(Rect(lr.x() + lr.width() + pad + 1, m_rect.y() + pad - 1, 
				  br.width(), br.height()));
     br = m_instAddButton.rect();
     m_instDelButton.setRect(Rect(br.x() + br.width() + pad + 1, m_rect.y() + pad - 1, 
				  br.width(), br.height()));
}

void InstrumentView::loadInstList() {
     Song *pSong = m_pApp->song();
     Instrument *pInst = NULL;
     m_instList.clearList();
     for (int i=0; i<pSong->instrumentCount(); i++) {
	  pInst = pSong->instrumentAt(i);
	  assert(pInst);
	  m_instList.addItem(pInst->name());
     }
     if (pSong->instrumentCount())
	  m_instList.setCurIndex(0);
     refresh();
}

void InstrumentView::keyDown(int keycode, int modifiers, int unichar) {
     if (keycode == ALLEGRO_KEY_DOWN && (modifiers & ALLEGRO_KEYMOD_CTRL))
	  m_instList.incCurIndex();
     else if (keycode == ALLEGRO_KEY_UP && (modifiers & ALLEGRO_KEYMOD_CTRL))
	  m_instList.decCurIndex();
     else
	  View::keyDown(keycode, modifiers, unichar);
}

void InstrumentView::addInst() {
     int chan=0;
     Song *pSong = m_pApp->song();
     int count = pSong->instrumentCount();
     if (count)
	  chan = pSong->instrumentAt(count - 1)->channel() + 1;
     m_pApp->song()->addInstrument(new Instrument(chan));
     m_instList.addItem("");
     refresh();
}

void InstrumentView::delInst() {
     Song *pSong = m_pApp->song();
     int count = pSong->instrumentCount();
     if (!count)
	  return;
     int i = count - 1;
     m_pApp->song()->removeInstrumentAt(i);
     m_instList.removeItemAt(i);
     refresh();
}
